package gcp.testes;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import java.util.HashMap;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;

import gcp.Amigo;
import gcp.Usuario;
import gcp.cadastros.CadastroAmigo;
import gcp.enums.Sexo;

import org.junit.Before;
import org.junit.Test;

/**
 * Classe de teste do CadastroAmigo.
 */
public class CadastroAmigoTeste {

    private CadastroAmigo cadastroAmigo;
    private Usuario usuario;
    private Amigo amigo1;
    private Amigo amigo2;
    private Amigo amigo3, amigo4;
  
    /**
     * Criação das variaveis.
     * @throws Exception Lancada quando algum parametro for nulo.
     */
    @Before
    public void inicializa() throws Exception {
    	cadastroAmigo = new CadastroAmigo();
        amigo1 = new Amigo("Catharine", "Quintans", Sexo.FEMININO);
        amigo2 = new Amigo("Natasha", "Bezerra", Sexo.FEMININO);
        amigo3 = new Amigo("Hildegard", "Furtado", Sexo.FEMININO);
        amigo4 = new Amigo("Brunno", "Almeida", Sexo.MASCULINO);
        usuario = new Usuario("Catharine", "Quintans", Sexo.FEMININO, "cathariine", "quintans");
        cadastroAmigo.adicionaAmigo(usuario, amigo1);
        cadastroAmigo.adicionaAmigo(usuario, amigo2);
    }

    /**
     * Testa adicionar amigos a facade.
     * @throws Exception Lancada quando algum parametro for nulo.
     */
    @Test
    public void testaAdicionaAmigo() throws Exception {
        assertEquals(2, cadastroAmigo.getNumeroDeAmigos(usuario));
        cadastroAmigo.adicionaAmigo(usuario, amigo3);
        assertEquals(3, cadastroAmigo.getNumeroDeAmigos(usuario));
    }

    /**
     * Testa o metodo getAmigo.
     * @throws Exception Lancada quando algum parametro for nulo.
     */
    @Test
    public void testaGetAmigo() throws Exception {
        assertEquals("testaGet 1", amigo1, cadastroAmigo.getAmigo(usuario, amigo1
                .getNome(), amigo1.getSobrenome()));
        assertEquals("testaGet 2", null, cadastroAmigo.getAmigo(usuario, amigo4
                .getNome(), amigo4.getSobrenome()));
        cadastroAmigo.adicionaAmigo(usuario, amigo4);
        assertEquals("testaGet 2", amigo4, cadastroAmigo.getAmigo(usuario, amigo4
                .getNome(), amigo4.getSobrenome()));
    }

    /**
     * Testa o metodo removeAmigo.
     * @throws Exception Lancada quando algum parametro for nulo.
     */
    @Test
    public void testaRemoveAmigo() throws Exception {

        assertEquals("testaRemoveAmigo 1", 2, cadastroAmigo
                .getNumeroDeAmigos(usuario));
        cadastroAmigo.removeAmigo(usuario, amigo1);
        cadastroAmigo.adicionaAmigo(usuario, amigo3);
        assertEquals("testaRemoveAmigo 2", 2, cadastroAmigo
                .getNumeroDeAmigos(usuario));
        cadastroAmigo.removeAmigo(usuario, amigo2);
        assertEquals("testaRemoveAmigo 3", 1, cadastroAmigo
                .getNumeroDeAmigos(usuario));
    }

    /**
     * Testa remover um amigo que nao existe. 
     * @throws Exception Lanca quando amigo nao exisitir
     */
    @Test(expected = Exception.class)
    public void testaRemoveAmigoInexistente() throws Exception {
        cadastroAmigo.removeAmigo(usuario, amigo3);
        assertEquals("testaRemoveAmigoInexistente1", 1, cadastroAmigo
                .getNumeroDeAmigos(usuario));
        cadastroAmigo.removeAmigo(usuario, amigo4);
        assertEquals("testa removerAmigoInexistente2", 1, cadastroAmigo
                .getNumeroDeAmigos(usuario));
    }

    /**
     * Testa a existencia de Amigod na lista de Amigos
     * @throws Exception
     */
    @Test
    public void testaGetListDeAmigo() throws Exception {
        assertTrue(cadastroAmigo.getList(usuario).contains(amigo1));
        assertTrue(cadastroAmigo.getList(usuario).contains(amigo2));
        cadastroAmigo.removeAmigo(usuario, amigo1);
        assertFalse(cadastroAmigo.getList(usuario).contains(amigo1));
        assertTrue(cadastroAmigo.getList(usuario).contains(amigo2));
        cadastroAmigo.removeAmigo(usuario, amigo2);
        assertFalse(cadastroAmigo.getList(usuario).contains(amigo1));
        assertFalse(cadastroAmigo.getList(usuario).contains(amigo2));
    }
    
    /**
     * Testa o metodo getAmigos.
     * @throws Exception 
     */
	@Test
    public void testaGetAmigos() throws Exception {
		assertTrue(cadastroAmigo.getAmigos().containsKey(usuario));
    	assertTrue(cadastroAmigo.getAmigos().get(usuario).contains(amigo1));
    	assertTrue(cadastroAmigo.getAmigos().get(usuario).contains(amigo2));
    	assertFalse(cadastroAmigo.getAmigos().get(usuario).contains(amigo3));
    	assertFalse(cadastroAmigo.getAmigos().get(usuario).contains(amigo4));
    	
    	cadastroAmigo.adicionaAmigo(usuario, amigo3);
    	cadastroAmigo.adicionaAmigo(usuario, amigo4);
    	   	
    	assertTrue(cadastroAmigo.getAmigos().get(usuario).contains(amigo3));
    	assertTrue(cadastroAmigo.getAmigos().get(usuario).contains(amigo4));
    	
    	cadastroAmigo.removeAmigo(usuario, amigo1);
    	cadastroAmigo.removeAmigo(usuario, amigo2);
    	
    	assertFalse(cadastroAmigo.getAmigos().get(usuario).contains(amigo1));
    	assertFalse(cadastroAmigo.getAmigos().get(usuario).contains(amigo2));
  	
    }
	
	/**
	 * Testa o metodo setAmigos.
	 */
	@Test
    public void testaSetAmigos() {
		List<Amigo> lista = new ArrayList<Amigo>();
		Map<Usuario, List<Amigo>> mapa = new HashMap<Usuario, List<Amigo>>();
		
		lista.add(amigo3);
		lista.add(amigo4);
		mapa.put(usuario,lista);
		cadastroAmigo.setAmigos(mapa); 
		
		assertFalse(cadastroAmigo.getAmigos().get(usuario).contains(amigo1));
    	assertFalse(cadastroAmigo.getAmigos().get(usuario).contains(amigo2));
		assertTrue(cadastroAmigo.getAmigos().get(usuario).contains(amigo3));
    	assertTrue(cadastroAmigo.getAmigos().get(usuario).contains(amigo4));
    	
    	lista.add(amigo1);
		lista.add(amigo2);
		mapa.put(usuario,lista);
		cadastroAmigo.setAmigos(mapa); 
		
		assertTrue(cadastroAmigo.getAmigos().get(usuario).contains(amigo1));
    	assertTrue(cadastroAmigo.getAmigos().get(usuario).contains(amigo2));
		assertTrue(cadastroAmigo.getAmigos().get(usuario).contains(amigo3));
    	assertTrue(cadastroAmigo.getAmigos().get(usuario).contains(amigo4));
	}	
}